package com.enjoylearning.media.service.jobhandler;

import com.enjoylearning.base.utils.Mp4VideoUtil;
import com.enjoylearning.media.model.po.MediaProcess;
import com.enjoylearning.media.service.MediaFileProcessService;
import com.enjoylearning.media.service.MediaFileService;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.*;

import static io.netty.handler.codec.http.HttpUtil.getMimeType;

/**
 * @author Mr.M
 * @version 1.0
 * @description TODO
 * @date 2022/10/15 11:58
 */
@Slf4j
@Component
public class VideoTask {

    @Autowired
    MediaFileService mediaFileService;
    @Autowired
    MediaFileProcessService mediaFileProcessService;


    @Value("${videoprocess.ffmpegpath}")
    String ffmpegpath;

    @XxlJob("videoJobHandler")
    public void videoJobHandler() throws Exception {

        // 分片参数
        int shardIndex = XxlJobHelper.getShardIndex();
        int shardTotal = XxlJobHelper.getShardTotal();
        List<MediaProcess> mediaProcessList = null;
        int size = 0;
        int processors = Runtime.getRuntime().availableProcessors();   //处理器核心数
        //查询待处理的任务
        mediaProcessList = mediaFileProcessService.getMediaProcessList(shardIndex, shardTotal, processors);
        //任务数量
        size = mediaProcessList.size();
        log.debug("取到的任务处理数:{}", size);
        if (size <= 0) {
            return;
        }
        //创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(size);
        //创建一个计数器
        CountDownLatch countDownLatch = new CountDownLatch(size);
        mediaProcessList.forEach(process -> {
            executorService.execute(() -> {
                try {
                    //判断视频格式
                    //文件扩展名
                    String extension = process.getFilename().substring(process.getFilename().lastIndexOf("."));
                    //文件mimeType
                    String mimeType = (String) getMimeType(extension);
                    if (mimeType.equals("video/mp4")){
                        log.debug("该视频已是MP4格式");
                        System.err.println("该视频已是MP4格式");

                        return;
                    }
                    //任务id
                    Long taskId = process.getId();
                    //开启任务
                    Boolean b = mediaFileProcessService.startTask(taskId);
                    if (!b) {
                        log.debug("抢占任务失败，任务ID:{}", taskId);
                        return;
                    }
                    //文件MD5值
                    String fileId = process.getFileId();
                    //ffmpeg的路径
                    String ffmpeg_path = ffmpegpath;//ffmpeg的安装位置
                    //下载minio视频到本地
                    File file = mediaFileService.downloadFileFromMinIO(process.getBucket(), process.getFilePath());
                    if (!file.exists()) {
                        log.debug("下载视频出错，任务ID:{},bucket:{},filePath:{}", taskId, process.getBucket(), process.getFilePath());
                        //保存任务处理失败的结果
                        mediaFileProcessService.saveProcessFinishStatus(taskId,"3",fileId,null,"下载视频到本地失败");
                        return;
                    }

                    //源avi视频的路径
                    String video_path = file.getAbsolutePath();
                    //转换后mp4文件的名称
                    String mp4_name = fileId+".mp4";
                    //转换后mp4文件的路径
                    //创建一个临时文件
                    File mp4File = null;
                    try {
                        mp4File = File.createTempFile("minio", ".mp4");
                    } catch (IOException e) {
                        log.debug("创建临时文件异常,{}", e.getMessage());
                        mediaFileProcessService.saveProcessFinishStatus(taskId,"3",fileId,null,"创建临时文件异常");
                        return;
                    }
                    String mp4_path = mp4File.getAbsolutePath();
                    //创建工具类对象
                    Mp4VideoUtil videoUtil = new Mp4VideoUtil(ffmpegpath,video_path,mp4_name,mp4_path);
                    //开始视频转换，成功将返回success
                    String s = videoUtil.generateMp4();
                    System.out.println(s);
                    if (!s.equals("success")){
                        log.debug("视频转码失败,原因:{},bucket:{},objectName:{}",s,process.getBucket(),process.getFilePath());
                        mediaFileProcessService.saveProcessFinishStatus(taskId,"3",fileId,null,"视频转码失败");
                        return;
                    }
                    //上传到minio
                    boolean b1 = mediaFileService.addMediaFilesToMinIO(mp4File.getAbsolutePath(), "video/mp4", process.getBucket(), process.getFilePath());
                    if (!b1){
                        log.debug("上传视频到minio失败,原因:{},tskId:{},objectName:{}",b1,taskId,process.getFilePath());
                        mediaFileProcessService.saveProcessFinishStatus(taskId,"3",fileId,null,"上传视频失败");
                        return;
                    }
                    //mp4文件的url
                    String url = getFilePath(fileId, ".mp4");

                    //保存任务处理结果
                    mediaFileProcessService.saveProcessFinishStatus(taskId,"2",fileId,url,"转码成功");
                    mp4File.delete();
                } finally {
                    countDownLatch.countDown();
                }
            });
        });
        //设置最大限度等待时间，阻塞对多等待一段时间
        countDownLatch.await(30,TimeUnit.MINUTES);


    }

    private String getFilePath(String fileMd5,String fileExt){
        return   fileMd5.substring(0,1) + "/" + fileMd5.substring(1,2) + "/" + fileMd5 + "/" +fileMd5 +fileExt;
    }

}